package com.rongzhe.house.user.service;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.rongzhe.house.common.cache.CommonCacheUtil;
import com.rongzhe.house.common.constants.Constants;
import com.rongzhe.house.common.enums.JpushMsgExtType;
import com.rongzhe.house.common.exception.RongZheBusinessException;
import com.rongzhe.house.common.utils.JPushUtil;
import com.rongzhe.house.common.utils.QiniuFileUploadUtil;
import com.rongzhe.house.common.utils.RandomNumberCode;
import com.rongzhe.house.jms.SmsProcessor;
import com.rongzhe.house.order.entity.OrderSnapshotContent;
import com.rongzhe.house.security.MD5Util;
import com.rongzhe.house.user.dao.UserBaseMapper;
import com.rongzhe.house.user.dao.UserComplaintSuggestMapper;
import com.rongzhe.house.user.dao.UserContractMapper;
import com.rongzhe.house.user.dao.UserIdentifyCardInfoMapper;
import com.rongzhe.house.user.entity.*;
import com.rongzhe.house.user.mapper.UserRoleMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.jms.Destination;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by JackWangon[www.aiprogram.top] 2017/7/29.
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserBaseMapper userMapper;

    @Autowired
    private CommonCacheUtil cacheUtil;

    @Autowired
    private SmsProcessor smsProcessor;

    @Autowired
    private UserContractMapper userContractMapper;

    @Autowired
    private UserIdentifyCardInfoMapper userIdentifyCardInfoMapper;

    @Autowired
    private UserComplaintSuggestMapper userComplaintSuggestMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private JPushUtil jPushUtil;

    private static final String VERIFYCODE_PREFIX = "verify.code.";
    private static final String SMS_QUEUE = "sms.queue";

    private static final String SUPER_CODE = "9527";

    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/7/31 23:15
     * @Description 登录业务
     */
    @Override
    @Transactional
    public String login(LoginInfo loginInfo) throws RongZheBusinessException {

        String decryptData = null;
        String token = null;
        try {
            //RSA解密AES的key
            // byte[] aesKey = RSAUtil.decryptByPrivateKey(Base64Util.decode(key));
            //AES的key解密AES加密数据
//            decryptData = AESUtil.decrypt(data, new String(aesKey, "UTF-8"));
//            if (decryptData == null) {
//                throw new Exception();
//            }
            //拿到提交数据 开始验证逻辑
            //JSONObject jsonObject = JSON.parseObject(decryptData);
            String mobile = loginInfo.getMobile();//电话
            String code = loginInfo.getCode();//验证码
            String platform = loginInfo.getPlatform();//机器类型
            String channelId = loginInfo.getChannelId();//推送频道编码 单个设备唯一

            //StringUtils.isBlank(platform)  || StringUtils.isBlank(channelId)
            if (StringUtils.isBlank(mobile) || StringUtils.isBlank(code)) {
                throw new Exception();
            }
            //去redis取验证码比较手机号码和验证码是否匹配 若匹配 说明是本人手机
            String verCode = cacheUtil.getCacheValue(VERIFYCODE_PREFIX + mobile);

            UserBase user = null;

            if (code.equals(verCode) || code.equals(SUPER_CODE)) {
                //检查用户是否存在
                user = userMapper.selectByMobile(mobile);

                if (user == null) {

                    //用户不存在 帮用户注册
                    user = new UserBase();
                    user.setMobile(mobile);
                    user.setNickname(mobile);
                    user.setLastLoginTime(new Date());
                    user.setLastDevice(loginInfo.getDevice());

                    //生成token
                    try {
                        token = this.generateToken(user);
                    } catch (Exception e) {
                        throw new RongZheBusinessException("fail.to.generate.token");
                    }

                    user.setToken(token);
                    userMapper.insertSelective(user);
                    //创建角色
                    UserRole userRole = new UserRole();
                    userRole.setUid(user.getId());
                    userRole.setRoleCode("Tenant");

                    userRoleMapper.insert(userRole);

                } else {


                    //删除之前的token
                    cacheUtil.remove(user.getToken());
                    //生成token
                    try {
                        token = this.generateToken(user);
                    } catch (Exception e) {
                        throw new RongZheBusinessException("fail.to.generate.token");
                    }


                    UserBase userBaseForUpdate = new UserBase();
                    userBaseForUpdate.setId(user.getId());
                    userBaseForUpdate.setLastDevice(loginInfo.getDevice());
                    userBaseForUpdate.setLastLoginTime(new Date());
                    userBaseForUpdate.setToken(token);
                    userMapper.updateByPrimaryKeySelective(userBaseForUpdate);

                    if (user.getLastDevice() != null
                            && !user.getLastDevice().equals(loginInfo.getDevice())) {
                        //如果设备信息不相同
                        //发送推送
                        jPushUtil.sendWithDevice(user.getLastDevice(), new HashMap<String, String>() {
                                    {
                                        //下线消息
                                        put("type", JpushMsgExtType.FORCE_EXIT.getType());
                                    }
                                },
                                JpushMsgExtType.FORCE_EXIT.getContent()
                        );


                    }
                }
            } else {
                throw new RongZheBusinessException("手机号与验证码不匹配");
            }


            UserElement ue = new UserElement();
            ue.setMobile(mobile);
            ue.setUserId(user.getId());
            ue.setToken(token);
            ue.setPlatform(platform);
            ue.setPushChannelId(channelId);
            cacheUtil.putTokenWhenLogin(ue);


        } catch (Exception e) {
            log.error("Fail to decrypt data", e);
            throw new RongZheBusinessException(e.getMessage());
        }

        return token;
    }

    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/8/4 11:49
     * @Description 修改用户昵称
     */

    @Transactional
    @Override
    public void modifyNickName(UserBase user) throws RongZheBusinessException {
        userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public UserIdentifyCardInfo addIdentifyCard(UserIdentifyCardInfo userIdentifyCardInfo) {

        UserIdentifyCardInfo userIdentifyCardInfoForUpdate = userIdentifyCardInfoMapper.selectByUidForUpdate(userIdentifyCardInfo.getUid());

        if (userIdentifyCardInfoForUpdate == null) {
            //TODO 魔数
            userIdentifyCardInfo.setState("2");
            userIdentifyCardInfo.setInsertTime(new Date());
            userIdentifyCardInfoMapper.insertSelective(userIdentifyCardInfo);
        } else {
            userIdentifyCardInfo.setId(userIdentifyCardInfoForUpdate.getId());
            //TODO 魔数
            userIdentifyCardInfo.setState("2");
            userIdentifyCardInfo.setUpdateTime(new Date());
            userIdentifyCardInfoMapper.updateByPrimaryKeySelective(userIdentifyCardInfo);
        }

        return userIdentifyCardInfo;
    }

    @Override
    public UserIdentifyCardInfo getIdentifyCardInfoByUid(Integer uid) {

        return userIdentifyCardInfoMapper.selectByUid(uid);

    }

    @Override
    public UserComplaintSuggest complaintSuggest(UserComplaintSuggest userComplaintSuggest) {
        userComplaintSuggest.setInsertTime(new Date());
        userComplaintSuggestMapper.insertSelective(userComplaintSuggest);
        return userComplaintSuggest;
    }

    @Override
    public List<UserComplaintSuggest> getComplaintSuggest(Integer currentPage, Integer pageSize, Integer currentUid) {

        PageHelper.startPage(currentPage, pageSize);

        PageHelper.orderBy("ucs.insert_time DESC");

        PageInfo<UserComplaintSuggest> pageInfo = new PageInfo(userComplaintSuggestMapper.selectList(currentUid));

        return pageInfo.getList();
    }

    @Override
    public List<UserContract> contractList(Integer currentPage, Integer pageSize, String uid) {

        PageHelper.startPage(currentPage, pageSize);

        PageHelper.orderBy("uc.insert_time DESC");

        PageInfo<UserContract> pageInfo = new PageInfo(userContractMapper.selectListByUid(uid));


        List<UserContract> userContracts = pageInfo.getList();


        if (!CollectionUtils.isEmpty(userContracts)) {

            for (UserContract userContract : userContracts) {
                userContract.setSnapshotContent(JSON.parseObject(userContract.getSnapshotStr(), OrderSnapshotContent.class));
                userContract.setSnapshotStr(null);
                if(StringUtils.isBlank(userContract.getApplyStatus())){
                    userContract.setApplyStatus("-1");
                }
            }

        }


        return pageInfo.getList();
    }

    @Override
    public UserContract contractDetail(Integer contractId) {

        UserContract userContract = userContractMapper.selectByPrimaryKey(contractId);


//        userContract.setHouseOverview();

        return null;
    }

    @Override
    public List<UserHouse> queryUserHouse(String uid) {
        return userContractMapper.queryUserHouse(uid);
    }

    @Override
    public void confirmContract(Integer id) {
        userContractMapper.updateConfirmContract(id);
    }

    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/8/5 17:22
     * @Description 上传头像
     */
    @Transactional
    @Override
    public String uploadHeadImg(MultipartFile file, Integer userId) throws RongZheBusinessException {

        try {
            //获取user 得到原来的头像地址
            UserBase user = userMapper.selectByPrimaryKey(userId);
            // 调用七牛
            String imgUrlName = Constants.QINIU_PROTOCOL + Constants.QINIU_HEAD_IMG_BUCKET_URL + "/" + QiniuFileUploadUtil.uploadHeadImg(file);
            user.setAvatar(imgUrlName);
            //更新用户头像URL
            userMapper.updateByPrimaryKeySelective(user);
            return imgUrlName;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RongZheBusinessException("头像上传失败");
        }
    }

    /**
     * @Author JackWang [www.coder520.com]
     * @Date 2017/8/5 17:27
     * @Description 发送验证码
     */
    @Override
    public void sendVercode(String mobile, String ip) throws RongZheBusinessException {
        String verCode = RandomNumberCode.verCode();
        //先存redis  reids缓存检查是否恶意请求 决定是否真的发送验证码
        int result = cacheUtil.cacheForVerificationCode(VERIFYCODE_PREFIX + mobile, verCode, "reg", 60, ip);
        if (result == 1) {
            log.info("当前验证码未过期，请稍后重试");
            throw new RongZheBusinessException("当前验证码未过期，请稍后重试");
        } else if (result == 2) {
            log.info("超过当日验证码次数上线");
            throw new RongZheBusinessException("超过当日验证码次数上限");
        } else if (result == 3) {
            log.info("超过当日验证码次数上限 {}", ip);
            throw new RongZheBusinessException(ip + "超过当日验证码次数上限");
        }
        log.info("Sending verify code {} for phone {}", verCode, mobile);
        //验证码推送到队列
        Destination destination = new ActiveMQQueue(SMS_QUEUE);
        Map<String, String> smsParam = new HashMap<>();
        smsParam.put("mobile", mobile);
        smsParam.put("tplId", Constants.ALSMS_VERCODE_TPLID);
        smsParam.put("vercode", verCode);
        String message = JSON.toJSONString(smsParam);
        smsProcessor.sendSmsToQueue(destination, message);
    }


    private String generateToken(UserBase user)
            throws Exception {
        String source = user.getId() + ":" + user.getMobile() + System.currentTimeMillis();
        return MD5Util.getMD5(source);
    }

    @Override
    public UserBase findById(Integer userId) {
        UserBase userBase = userMapper.selectDetailByPrimaryKey(userId);

        if (userBase.getIdentityState() == null) {
            //魔数 TODO
            userBase.setIdentityState(0);
        }

        return userBase;
    }


}
